﻿using Net.Share;
using Net.System;
using System.Net.Sockets;
using Cysharp.Threading.Tasks;

namespace Net.Client
{
    /// <summary>
    /// Udp网络客户端
    /// 在安卓端必须设置可以后台运行, 如果不设置,当你按下home键后,app的所有线程将会被暂停,这会影响网络心跳检测线程,导致网络中断
    /// 解决方法 : 在android项目AndroidManifest.xml文件中的activity中添加如下内容：
    /// android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" 
    /// 详情请看此博文:https://www.cnblogs.com/nanwei/p/9125316.html
    /// 或这个博文: http://www.voidcn.com/article/p-yakpcmce-bpk.html
    /// </summary>
    public class UdpClient : ClientBase
    {
        public IGcp Gcp { get; internal set; }

        protected override void OnSocketConnect(string ipAddress, int port)
        {
            base.OnSocketConnect(ipAddress, port);
            Gcp = new Plugins.GcpKernel
            {
                MTU = (ushort)Config.MTU,
                RTO = Config.RTO,
                MTPS = Config.MTPS,
                FlowControl = Config.FlowControl,
                RemotePoint = Client.RemoteEndPoint
            };
            Gcp.OnSender += (remotePoint, segment) =>
            {
                trafficStatistics.SentPacketsPerSecond++;
                trafficStatistics.SentBytesPerSecond += segment.Count;
                Client.SendTo(segment.Buffer, segment.Offset, segment.Count, SocketFlags.None, remotePoint);
            };
        }

        public override void ReceiveHandler()
        {
            if (Client == null)
                return;
            if (!Client.Connected)
            {
                if (Connected)
                    ConnectLost(SocketError.NotConnected);
                return;
            }
            if (Client.Poll(performance, SelectMode.SelectRead))
            {
                var segment = BufferPool.Take(config.ReceiveBufferSize);
                segment.Count = Client.Receive(segment.Buffer, 0, segment.Length, SocketFlags.None, out SocketError error);
                if (segment.Count == 0 | error != SocketError.Success)
                {
                    BufferPool.Push(segment);
                    if (Connected) //如果是连接完成状态下才能触发连接中断, 要不然还没连接成功就触发连接中断就很不正常
                        ConnectLost(error);
                    return;
                }
                //ReceiveHandler(ref segment);
                Gcp.Input(segment);
                BufferPool.Push(segment);
                while (Gcp.Receive(out var segment1) > 0)
                {
                    ReceiveHandler(ref segment1);
                    BufferPool.Push(segment1);
                }
            }
        }

        protected override void SendByteData(ISegment buffer)
        {
            Gcp.Send(buffer);
        }

        public override void OnNetworkTick()
        {
            base.OnNetworkTick();
            Gcp?.Update();
        }
    }

    /// <summary>
    /// Gcp协议
    /// </summary>
    public class GcpClient : UdpClient
    {
    }
}
